import os
import shutil
import subprocess
import sys
import PySimpleGUI as sg
from pathlib import Path
from datetime import datetime

# 修复高DPI感知
if sys.platform == 'win32':
    try:
        import ctypes

        ctypes.OleDLL('shcore').SetProcessDpiAwareness(1)
    except (ImportError, AttributeError, OSError):
        pass


# def get_parr_empty(x):
#     parr = x.parent
#     if not list(f for f in parr.glob('**/*.*') if f.is_file()):
#         return get_parr_empty(parr)
#     else:
#         return x

# def get_parr_empty(x):
#     parr = x.parent
#     try:
#         next(f for f in parr.glob('**/*.*') if f.is_file())  # 尝试从生成器中获取第一个文件
#     except StopIteration:  # 如果没有文件，则递归调用函数
#         return get_parr_empty(parr)
#     else:
#         return x  # 如果有文件，则直接返回当前的x

def get_parr_empty(x, depth=0, max_depth=20):
    if depth > max_depth:
        raise RecursionError("递归深度超限.")
    parr = x.parent
    try:
        next(f for f in parr.glob('**/*') if f.is_file())
    except StopIteration:
        if parr == parr.root:
            return None  # 或者根据需求返回一个特定值
        return get_parr_empty(parr, depth + 1)
    else:
        return x


def find_empty_dirs(path):
    empty_set = set()
    count = 0
    for x in path.glob('**/'):
        count += 1
        if x.is_dir():
            try:
                next(f for f in x.glob('*'))
            except StopIteration:
                empty_set.add(x)

    print(f'检查目录:{count},空目录:{len(empty_set)}')
    window['-TIPS-'].update(f'检查目录:{count},空目录:{len(empty_set)}')
    return empty_set  # 返回包含所有空目录路径的集合


# def find_empty_dirs(path):
#     empty_set = set()
#     for x in path.glob('**/'):
#         if x.is_dir() and not list(x.glob('*')):
#             empty_set.add(get_parr_empty(x))
#     # 返回包含所有空目录路径的集合
#     return empty_set

def delete_dir(dir):
    try:
        parr = dir.parent
        shutil.rmtree(dir)
        try:
            next(f for f in parr.glob('*'))
        except StopIteration:
            delete_dir(parr)
    except OSError as e:
        print(f"无法删除 {dir}: {e.strerror}")


def delete_dirs(dirs):
    del_fail = []
    succ_count = 0
    for dir in dirs:
        try:
            delete_dir(dir)
            succ_count += 1
            write_log('log.txt', f"删除目录: {dir}")
        except OSError as e:
            print(f"无法删除 {dir}: {e.strerror}")
            del_fail.append(dir)
            write_log('log.txt', f"删除失败: {dir}")
    window['clean_res'].update(f"删除成功: {succ_count}，删除失败: {len(del_fail)}")
    return del_fail


# 写入日志函数


def write_log(log_file, message):
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")  # 获取当前时间并格式化
    log_message = f"{timestamp} {message}\n"  # 在消息前添加时间戳
    with open(log_file, 'a', encoding='utf-8') as f:
        f.write(log_message)


# 1. 定义GUI布局
layout = [
    [
        sg.Text('选择路径:'),
        sg.Input(key='-FOLDER-', enable_events=True, default_text=os.getcwd()),
        sg.FolderBrowse('浏览'),
        sg.Button('搜索空目录', key='-SEARCH-'),
        # sg.Checkbox('向上递归', default=False, key='-RECURSIVE-',
        #             tooltip='如果选中，程序将逐级向上递归查找最上层空目录。'),
        sg.Text('', key='-TIPS-', text_color='yellow')
    ],
    [sg.Listbox(values=[], size=(120, 30), key='-EMPTY_DIRS-', enable_events=True)],
    [
        sg.Button('全选', key='-SELECT_ALL-'),
        sg.Button('反选', key='-INVERT_SELECT-'),
        sg.Button('清理', key='-CLEANUP-', button_color=('white', 'red')),
        sg.Button('打印', key='-PRINT-'),
        sg.Button('浏览', key='-BROWSE-'),
        sg.Button('日志', key='-LOG-'),
        sg.Text('', key='clean_res')
    ],
]

window = sg.Window('空目录清理工具', layout)

# 2. GUI事件处理循环
while True:
    event, values = window.read()

    if event == sg.WINDOW_CLOSED:
        break

    # 搜索按钮被点击
    elif event == '-SEARCH-':
        folder_path = Path(values['-FOLDER-'])
        empty_dirs = find_empty_dirs(folder_path)
        window['-EMPTY_DIRS-'].update(empty_dirs)

    # 全选按钮被点击
    elif event == '-SELECT_ALL-':
        selected = window['-EMPTY_DIRS-'].get_list_values()
        window['-EMPTY_DIRS-'].update(set_to_index=[i for i in range(len(selected))])

    # 反选按钮被点击
    elif event == '-INVERT_SELECT-':
        selected = window['-EMPTY_DIRS-'].get_indexes()
        all_indexes = list(range(len(window['-EMPTY_DIRS-'].get_list_values())))
        window['-EMPTY_DIRS-'].update(set_to_index=list(set(all_indexes) - set(selected)))

    # 清理按钮被点击
    elif event == '-CLEANUP-':
        selected_dirs = [Path(window['-EMPTY_DIRS-'].get_list_values()[i]) for i in
                         window['-EMPTY_DIRS-'].get_indexes()]
        del_f = delete_dirs(selected_dirs)
        window['-EMPTY_DIRS-'].update(values=del_f)

    # 打印按钮被点击时输出已选择路径
    elif event == '-PRINT-':
        selected_dirs = [Path(window['-EMPTY_DIRS-'].get_list_values()[i]) for i in
                         window['-EMPTY_DIRS-'].get_indexes()]
        for x in selected_dirs:
            print(x)

    # 浏览按钮被点击时如果已选择路径数量为1则用explorer打开，多个则弹框提示只能选择一个
    elif event == '-BROWSE-':
        selected_dirs = [Path(window['-EMPTY_DIRS-'].get_list_values()[i]) for i in
                         window['-EMPTY_DIRS-'].get_indexes()]
        if len(selected_dirs) == 1:
            try:
                subprocess.run(f'explorer {selected_dirs[0]}')
            except OSError as e:
                sg.popup_error(f"无法打开 {selected_dirs[0]}: {e.strerror}")
        else:
            sg.popup_quick('只能选择一个路径打开')

    elif event == '-LOG-':
        subprocess.run(f'notepad log.txt')

# 关闭窗口
window.close()
